package com.example.test.config.aop;


import cn.hutool.core.util.HashUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;

/**
 * 重复提交校验处理切面
 *
 * @author tyd
 * @date 2021/2/1
 */
@Aspect
@Component
@Slf4j
public class NoRepeatSubmitAspect {

    @Autowired
    private RedisLocker redisLocker;

    @Pointcut("@annotation(com.example.test.config.NoRepeatSubmit)")
    public void noRepeatSubmit() {
    }

    @Around(value = "noRepeatSubmit()")
    public Object checkRepeatSubmit(ProceedingJoinPoint jp) throws Throwable {

        // 获取请求参数
        String paramJSON = JSONUtil.toJsonStr(jp.getArgs());
        // 计算请求参数hash值
        String hash = String.valueOf(HashUtil.fnvHash(paramJSON));
        // 获取到分布式锁，如果获取不到，说明重复提交，直接丢弃
        LockContext lockContext = redisLocker.getKey(hash);
        if (lockContext != null) {
            log.info("获取到锁：{}", lockContext.getKey());
            Object reuslt = jp.proceed();
            redisLocker.releaseLock(lockContext);
            log.info("释放锁锁：{}", lockContext.getKey());
            return reuslt;
        }
        System.out.println("未执行");
        return null;
    }

    public HttpServletRequest getRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest httpRequest = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);

        return httpRequest;
    }
}
